<html>
<head><meta charset="utf-8"></head>
<body>
	<script type="text/javascript">

        const log = (...params) => {
            document.write(params.join(" ")+"<br>");
        };

        function reqAsPromise(req) {
            return new Promise((resolve, reject) => {
                req.onsuccess = () => resolve(req.result);
                req.onerror = (err) => reject(err);
            });
        }

        function txnAsPromise(txn) {
            return new Promise((resolve, reject) => {
                txn.addEventListener("complete", resolve);
                txn.addEventListener("abort", reject);
            });
        }

        function openDatabase(name, createObjectStore, version) {
            const req = indexedDB.open(name, version);
            req.onupgradeneeded = (ev) => {
                const db = ev.target.result;
                const txn = ev.target.transaction;
                const oldVersion = ev.oldVersion;
                createObjectStore(db, txn, oldVersion, version);
            }; 
            return reqAsPromise(req);
        }

        async function detectWebkitEarlyCloseTxnBug() {
            const dbName = "webkit_test_inactive_txn_" + Math.random() * Number.MAX_SAFE_INTEGER;
            try {
                const db = await openDatabase(dbName, db => {
                    db.createObjectStore("test", {keyPath: "key"});
                }, 1);
                const readTxn = db.transaction(["test"], "readonly");
                await reqAsPromise(readTxn.objectStore("test").get("somekey"));
                // schedule a macro task in between the two txns
                await new Promise(r => setTimeout(r, 0));
                const writeTxn = db.transaction(["test"], "readwrite");
                await Promise.resolve();
                writeTxn.objectStore("test").add({key: "somekey", value: "foo"});
                await txnAsPromise(writeTxn);
            } catch (err) {
                if (err.name === "TransactionInactiveError") {
                    return true;
                }
            } finally {
                try {
                    indexedDB.deleteDatabase(dbName);
                } catch (err) {}
            }
            return false;
        }

        (async () => {
            if (await detectWebkitEarlyCloseTxnBug()) {
                log("the test failed, your browser seems to have the bug");
            } else {
                log("the test succeeded, your browser seems fine");
            }
        })();

	</script>
</body>
</html>
